﻿/*****************************
 * 获取策略：
 * 1.先获取Unit1的广告，
 * 成功，便后面用于播放
 * 失败，则
 * 2.获取Unit2的广告
 * 成功，便留着用于播放
 * 失败，从步骤1开始循环
 * 
 * 若 Unit1 的价格要比 Unit2 高，可以采用  在未播放之前不断获取ID1的广告
 * 
 * *******************************/

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public enum ADType
{
    /// <summary>
    /// 插屏
    /// </summary>
    Interstitial,
    /// <summary>
    /// 奖励广告
    /// </summary>
    Incentivized,
    /// <summary>
    /// 横幅
    /// </summary>
    Banner,
}

public class AdsManager : MonoSingleton<AdsManager>
{
    public class AdInfo
    {
        /// <summary>
        /// 可用的广告unit列表
        /// </summary>
        public string[] AdUnits;
        /// <summary>
        /// 用于获取广告的unit index
        /// </summary>
        public int AdIndex;
        /// <summary>
        /// 是否获取到广告
        /// </summary>
        public bool HasAd;
        /// <summary>
        /// 正在获取广告
        /// </summary>
        public bool FetchingAd;
        /// <summary>
        /// 获取到广告的unitid
        /// </summary>
        public string SucceedUnitID;

        public void LoadedAd(string unitid)
        {
            SucceedUnitID = unitid;
            HasAd = true;
            AdIndex = 0;
        }
        public void CalculateNewIndex() {
            AdIndex = (AdIndex + 1) % AdUnits.Length;
        }
    }

    /*
     * 下标顺序作为优先级获取广告
     * 若0能获取到，则一直用0
     */
    private readonly string[] _bannerAdUnits = { "b195f8dd8ded45fe847ad89ed1d016da" };
    private readonly string[] _interstitialAdUnits = { "24534e1901884e398f1253216226017e" };
    private readonly string[] _rewardedVideoAdUnits = { "920b6145fb1546cf8b5cf2ac34638bb7" };
    private readonly string[] _rewardedRichMediaAdUnits = { "a96ae2ef41d44822af45c6328c4e1eb1" };

    private AdInfo _bannerAd;
    private AdInfo _interstitialAd;
    private AdInfo _rewardedVideoAd;

    public System.Action<bool> OnIncentivizedAdClose;
    public System.Action OnInterstitiaClose;
    public bool isOpenAd = false;
    public MoPub.AdPosition BannerPosition = MoPubBase.AdPosition.BottomCenter;

    /// <summary>
    /// 在还没获取到banner的时候,记录需要显示banner的意图
    /// 待获取到后直接显示
    /// </summary>
    private bool _wannerShowBanner = false;

    public void Initialize()
    {
        if (CheckPlatform())
            return;

        _bannerAd = new AdInfo {
            AdUnits = _bannerAdUnits,
            AdIndex = 0,
            HasAd = false,
        };
        _interstitialAd = new AdInfo
        {
            AdUnits = _interstitialAdUnits,
            AdIndex = 0,
            HasAd = false,
        };
        _rewardedVideoAd = new AdInfo
        {
            AdUnits = _rewardedVideoAdUnits,
            AdIndex = 0,
            HasAd = false,
        };

        isOpenAd = false;
        RegisterListeners();
        InitAdSdk();
    }
    public void Uninitialize()
    {
        UnregisterListeners();
    }

    private void InitAdSdk()
    {
        //用任意一个ID来初始化均可
        var anyAdUnitId = _interstitialAdUnits[0];
        MoPub.InitializeSdk(new MoPub.SdkConfiguration
        {
            AdUnitId = anyAdUnitId,
            LogLevel = MoPubBase.LogLevel.MPLogLevelDebug,
        });

        MoPub.LoadBannerPluginsForAdUnits(_bannerAdUnits);
        MoPub.LoadInterstitialPluginsForAdUnits(_interstitialAdUnits);
        MoPub.LoadRewardedVideoPluginsForAdUnits(_rewardedVideoAdUnits);
    }
      
    public void FetchAllAd()
    {
        FetchAd(ADType.Incentivized);
        FetchAd(ADType.Interstitial);
        FetchAd(ADType.Banner);
    }

    public void FetchAd(ADType type)
    {
        PutLog("FetchAd " + type.ToString());
        switch (type)
        {
            case ADType.Interstitial:
                if (_interstitialAd.FetchingAd)
                    return;
                _interstitialAd.HasAd = false;
                _interstitialAd.FetchingAd = true;
                MoPub.RequestInterstitialAd(_interstitialAd.AdUnits[_interstitialAd.AdIndex]);
                break;
            case ADType.Incentivized:
                if (_rewardedVideoAd.FetchingAd)
                {
                    PutLog("_rewardedVideoAd.FetchingAd = true; return");
                    return;
                }
                _rewardedVideoAd.HasAd = false;
                _rewardedVideoAd.FetchingAd = true;
                MoPub.RequestRewardedVideo(_rewardedVideoAd.AdUnits[_rewardedVideoAd.AdIndex]);
                break;
            case ADType.Banner:
                if (_bannerAd.FetchingAd)
                    return;
                _bannerAd.HasAd = false;
                _bannerAd.FetchingAd = true;
                MoPub.CreateBanner(_bannerAd.AdUnits[_bannerAd.AdIndex], BannerPosition);
                break;
        }
    }

    private bool CheckPlatform()
    {
        return Application.platform != RuntimePlatform.Android && Application.platform != RuntimePlatform.IPhonePlayer;
    }
    public bool IsAvailable(ADType type)
    {
        bool result = false;
        switch (type)
        {
            case ADType.Interstitial:
                result = _interstitialAd.HasAd;
                break;
            case ADType.Incentivized:
                result = _rewardedVideoAd.HasAd;
                break;
            case ADType.Banner:
                result = _bannerAd.HasAd;
                break;
        }
        return result;
    }
    #region 广告展示接口
    public void ShowBannerAd()
    {
        PutLog("ShowBannerAd");
        //if (PlayerRecords.Instance.isRemoveBanner)
        //    return;
        if (CheckPlatform())
            return;
        _wannerShowBanner = true;
        if (_bannerAd.HasAd)
        {
            PutLog("ShowBannerAd 2");
            MoPub.ShowBanner(_bannerAd.SucceedUnitID, true);
        }        
    }

    public void HideBannerAd()
    {
        PutLog("HideBannerAd");
        if (CheckPlatform())
            return;
        _wannerShowBanner = false;
        PutLog("HideBannerAd 2");
        if (string.IsNullOrEmpty(_bannerAd.SucceedUnitID))
            return;
        MoPub.ShowBanner(_bannerAd.SucceedUnitID, false);
    }

    public void DestroyBannerAd()
    {
        PutLog("DestroyBannerAd");
        if (CheckPlatform())
            return;
        _wannerShowBanner = false;
        PutLog("DestroyBannerAd 2");
        _bannerAd.HasAd = false;
        if (string.IsNullOrEmpty(_bannerAd.SucceedUnitID))
            return;
        MoPub.DestroyBanner(_bannerAd.SucceedUnitID);
    }

    public void ShowIncentivized()
    {
        PutLog("ShowIncentivized");
        if (CheckPlatform())
            return;
        if (!_rewardedVideoAd.HasAd)
        {
            FetchAd(ADType.Incentivized);
            return;
        }
        isOpenAd = true;        
        PutLog("ShowIncentivized 2");
        MoPub.ShowRewardedVideo(_rewardedVideoAd.SucceedUnitID);
    }

    public void ShowInterstitial()
    {
        PutLog("ShowInterstitial");
        //if (PlayerData.Instance.isRemoveBanner)
        //   return;
        if (CheckPlatform())
            return;        
        if (!_interstitialAd.HasAd)
        {
            FetchAd(ADType.Interstitial);
            return;
        }
        isOpenAd = true;
        PutLog("ShowInterstitial 2");
        MoPub.ShowInterstitialAd(_interstitialAd.SucceedUnitID);
    }
    
    #endregion

    #region listeners

    private void RegisterListeners()
    {
        MoPubManager.OnSdkInitializedEvent += OnSdkInitializedEvent;

        MoPubManager.OnAdLoadedEvent += OnBannerLoadedEvent;
        MoPubManager.OnAdFailedEvent += OnBannerFailedEvent;

        MoPubManager.OnInterstitialLoadedEvent += OnInterstitialLoadedEvent;
        MoPubManager.OnInterstitialFailedEvent += OnInterstitialFailedEvent;
        MoPubManager.OnInterstitialDismissedEvent += OnInterstitialDismissedEvent;
        MoPubManager.OnInterstitialShownEvent += OnInterstitialShownEvent;
#if UNITY_IOS
        MoPubManager.OnInterstitialExpiredEvent += OnInterstitialExpiredEvent;
#endif

        MoPubManager.OnRewardedVideoLoadedEvent += OnRewardedVideoLoadedEvent;
        MoPubManager.OnRewardedVideoFailedEvent += OnRewardedVideoFailedEvent;
        MoPubManager.OnRewardedVideoFailedToPlayEvent += OnRewardedVideoFailedToPlayEvent;
        MoPubManager.OnRewardedVideoClosedEvent += OnRewardedVideoClosedEvent;
        MoPubManager.OnRewardedVideoReceivedRewardEvent += OnRewardedVideoReceivedRewardEvent;

        MoPubManager.OnConsentStatusChangedEvent += OnConsentStatusChangedEvent;
        MoPubManager.OnConsentDialogLoadedEvent += OnConsentDialogLoadedEvent;
        MoPubManager.OnConsentDialogFailedEvent += OnConsentDialogFailedEvent;
        MoPubManager.OnConsentDialogShownEvent += OnConsentDialogShownEvent;
    }
    private void UnregisterListeners()
    {
        MoPubManager.OnSdkInitializedEvent -= OnSdkInitializedEvent;

        MoPubManager.OnAdLoadedEvent -= OnBannerLoadedEvent;
        MoPubManager.OnAdFailedEvent -= OnBannerFailedEvent;

        MoPubManager.OnInterstitialLoadedEvent -= OnInterstitialLoadedEvent;
        MoPubManager.OnInterstitialFailedEvent -= OnInterstitialFailedEvent;
        MoPubManager.OnInterstitialDismissedEvent -= OnInterstitialDismissedEvent;
        MoPubManager.OnInterstitialShownEvent -= OnInterstitialShownEvent;

#if UNITY_IOS
        MoPubManager.OnInterstitialExpiredEvent -= OnInterstitialExpiredEvent;
#endif

        MoPubManager.OnRewardedVideoLoadedEvent -= OnRewardedVideoLoadedEvent;
        MoPubManager.OnRewardedVideoFailedEvent -= OnRewardedVideoFailedEvent;
        MoPubManager.OnRewardedVideoFailedToPlayEvent -= OnRewardedVideoFailedToPlayEvent;
        MoPubManager.OnRewardedVideoClosedEvent -= OnRewardedVideoClosedEvent;
        MoPubManager.OnRewardedVideoReceivedRewardEvent -= OnRewardedVideoReceivedRewardEvent;

        MoPubManager.OnConsentStatusChangedEvent -= OnConsentStatusChangedEvent;
        MoPubManager.OnConsentDialogLoadedEvent -= OnConsentDialogLoadedEvent;
        MoPubManager.OnConsentDialogFailedEvent -= OnConsentDialogFailedEvent;
        MoPubManager.OnConsentDialogShownEvent -= OnConsentDialogShownEvent;
    }

    private void OnSdkInitializedEvent(string adUnitId)
    {
        PutLog("OnSdkInitializedEvent ShouldShowConsentDialog="+ MoPub.ShouldShowConsentDialog);
        if (MoPub.ShouldShowConsentDialog)
        {
            MoPub.LoadConsentDialog();
        }
        FetchAllAd();
    }

#region Banner Events 

    private void OnBannerLoadedEvent(string adUnitId, float height)
    {
        PutLog("OnBannerLoadedEvent("+"h" + height + ")", adUnitId);
        _bannerAd.FetchingAd = false;
        _bannerAd.LoadedAd(adUnitId);

        if (_wannerShowBanner)
        {
            ShowBannerAd();
        }
        else
        {
            HideBannerAd();
        }
    }

    private void OnBannerFailedEvent(string adUnitId, string error)
    {
        AdFailedLog(adUnitId, "load banner", error);
        _bannerAd.FetchingAd = false;
        _bannerAd.CalculateNewIndex();
        FetchAd(ADType.Banner);
    }
#endregion

#region Interstitial Events

    private void OnInterstitialLoadedEvent(string adUnitId)
    {
        PutLog("OnInterstitialLoadedEvent", adUnitId);
        _interstitialAd.FetchingAd = false;
        _interstitialAd.LoadedAd(adUnitId);
    }
    
    private void OnInterstitialFailedEvent(string adUnitId, string error)
    {
        AdFailedLog(adUnitId, "load interstitial", error);
        _interstitialAd.FetchingAd = false;
        _interstitialAd.CalculateNewIndex();
        FetchAd(ADType.Interstitial);
    }
    /// <summary>
    /// 播放被驳回
    /// </summary>
    /// <param name="adUnitId"></param>
    private void OnInterstitialDismissedEvent(string adUnitId)
    {
        PutLog("OnInterstitialDismissedEvent", adUnitId);
        FetchAd(ADType.Interstitial);
        if (OnInterstitiaClose != null)
            OnInterstitiaClose();
    }

    private void OnInterstitialShownEvent(string adUnitId)
    {
        PutLog("OnInterstitialShownEvent", adUnitId);
        isOpenAd = false;
        FetchAd(ADType.Interstitial);
        if (OnInterstitiaClose != null)
            OnInterstitiaClose();
    }

    /// <summary>
    /// ios only
    /// </summary>
    /// <param name="adUnitId"></param>
    private void OnInterstitialExpiredEvent(string adUnitId)
    {
        PutLog("OnInterstitialExpiredEvent", adUnitId);
        isOpenAd = false;
        FetchAd(ADType.Interstitial);
    }

    #endregion

    #region Rewarded Video Events
        
    private void OnRewardedVideoLoadedEvent(string adUnitId)
    {
        PutLog("OnRewardedVideoLoadedEvent", adUnitId);
        //var availableRewards = MoPub.GetAvailableRewards(adUnitId);
        _rewardedVideoAd.FetchingAd = false;
        _rewardedVideoAd.LoadedAd(adUnitId);
    }


    private void OnRewardedVideoFailedEvent(string adUnitId, string error)
    {
        AdFailedLog(adUnitId, "load rewarded video", error);
        _rewardedVideoAd.FetchingAd = false;
        _rewardedVideoAd.CalculateNewIndex();
        FetchAd(ADType.Incentivized);
    }


    private void OnRewardedVideoFailedToPlayEvent(string adUnitId, string error)
    {
        AdFailedLog(adUnitId, "play rewarded video", error);
        isOpenAd = false;
        if (OnIncentivizedAdClose != null)
            OnIncentivizedAdClose(false);
    }

    private void OnRewardedVideoClosedEvent(string adUnitId)
    {
        PutLog("OnRewardedVideoClosedEvent", adUnitId);
        isOpenAd = false;
        if (OnIncentivizedAdClose != null)
            OnIncentivizedAdClose(false);
        FetchAd(ADType.Incentivized);
    }
    private void OnRewardedVideoReceivedRewardEvent(string adUnitId, string lbl, float amount)
    {
        PutLog("OnRewardedVideoReceivedRewardEvent", adUnitId);
        isOpenAd = false;
        if (OnIncentivizedAdClose != null)
            OnIncentivizedAdClose(true);
        //FetchAd(ADType.Incentivized);
    }
    #endregion

    #region GDPR
    private void OnConsentStatusChangedEvent(MoPub.Consent.Status oldStatus, MoPub.Consent.Status newStatus,
                                            bool canCollectPersonalInfo)
    {
        PutLog("OnConsentStatusChangedEvent: " + oldStatus.ToString() + " " + newStatus.ToString() + " " + canCollectPersonalInfo.ToString());
    }

    private void OnConsentDialogLoadedEvent()
    {
        PutLog("OnConsentDialogLoadedEvent");
        MoPub.ShowConsentDialog();
    }

    private void OnConsentDialogFailedEvent(string err)
    {
        PutLog("OnConsentDialogFailedEvent");
        if (MoPub.ShouldShowConsentDialog)
        {
            MoPub.LoadConsentDialog();
        }
    }

    private void OnConsentDialogShownEvent()
    {
        PutLog("OnConsentDialogShownEvent");
    }
    #endregion

    #endregion

    private void AdFailedLog(string adUnitId, string action, string error)
    {
        var errorMsg = "Failed to " + action + " ad unit " + adUnitId;
        if (!string.IsNullOrEmpty(error))
            errorMsg += ": " + error;

        PutLog(errorMsg);
    }

    private void PutLog(string str)
    {
        Debug.Log(string.Format("______AdsManagerLog:{0}",str));
    }
    private void PutLog(string str ,string str2)
    {
        PutLog(str + "-" + str2);
    }
}
